package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.BooleanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author wxh
 * @since 2024-08-25
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
    private final UserClient userClient;
    private final InteractionReplyMapper replyMapper;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;

    /**
     * 新增问题
     *
     * @param questionFormDTO
     */
    @Override
    public void saveQuestion(QuestionFormDTO questionFormDTO) {
        //1.属性拷贝
        InteractionQuestion interactionQuestion = BeanUtils.copyBean(questionFormDTO, InteractionQuestion.class);
        //2.设置userId
        interactionQuestion.setUserId(UserContext.getUser());
        //3.插入数据库
        save(interactionQuestion);

    }

    /**
     * 分页查询问题和回复
     *
     * @param questionPage
     * @return
     */
    @Override
    public PageDTO<QuestionVO> queryPageQuestion(QuestionPageQuery questionPage) {
        //1.判断课程id和小节id是否传入一个
        Long courseId = questionPage.getCourseId();
        Long sectionId = questionPage.getSectionId();
        if (ObjectUtil.isEmpty(courseId) && ObjectUtil.isEmpty(sectionId)) {
            throw new BadRequestException("课程id和小节id必须传一个");
        }
        //2.分页查询interaction_question表  管理员隐藏的不查
        //select * from interaction_question where course_id = 3 and user_id = 2 and section_id = 1 and hidden = 0
        // order by create_time desc limit 0,10;
        Page<InteractionQuestion> pageQuestion = this.lambdaQuery()
                .select(InteractionQuestion.class, column -> !column.getColumn().equals("description"))
                .eq(ObjectUtil.isNotEmpty(courseId), InteractionQuestion::getCourseId, courseId)
                .eq(ObjectUtil.isNotEmpty(sectionId), InteractionQuestion::getSectionId, sectionId)
                .eq(BooleanUtils.isTrue(questionPage.getOnlyMine()), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .page(questionPage.toMpPageDefaultSortByCreateTimeDesc());
        //2.1对分页查询出的数据判空
        List<InteractionQuestion> records = pageQuestion.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(pageQuestion);
        }
        //3.查询用户信息
        //3.0收集提问者用户ids 和 最近一个回答问题的ids
        //Set<Long> userIds = records.stream().map(InteractionQuestion::getUserId).collect(Collectors.toSet());
        Set<Long> userIds = new HashSet<>(records.size());
        //3.1收集最后一次回答用户ids
        Set<Long> answerIds = new HashSet<>(records.size());
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            answerIds.add(record.getLatestAnswerId());
        }
        //4.查询最近一次回答的内容，查询interaction_reply表
        Map<Long, InteractionReply> replyMap = new HashMap<>(answerIds.size());
        List<InteractionReply> replyList = replyMapper.selectBatchIds(answerIds);
        if (ObjectUtil.isNotEmpty(replyList)) {
            //没有匿名的人赋值名称
            for (InteractionReply reply : replyList) {
                replyMap.put(reply.getId(), reply);
                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId());
                }
            }
        }

        //5.分装提问者用户信息
        //5.1将userInfos转为map，key为用户的id ，value为用户信息对象
        Map<Long, UserDTO> userInfoMap = new HashMap<>(userIds.size());
        //5.3健壮性判断
        if (ObjectUtil.isNotEmpty(userIds)) {
            //5.1.1查询提问者用户信息
            List<UserDTO> userInfos = userClient.queryUserByIds(userIds);
            if (ObjectUtil.isNotEmpty(userInfos)) {
                userInfoMap = userInfos.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
            }
        }
        //6.数据分装
        List<QuestionVO> voList = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            //6.1属性拷贝
            QuestionVO vo = BeanUtils.copyBean(record, QuestionVO.class);
            //6.2拿到userInfoMap里面的用户信息
            UserDTO userDTO = userInfoMap.get(record.getUserId());
            //提问者信息分装
            if (ObjectUtil.isNotEmpty(userDTO)) {
                if(!record.getAnonymity()){
                vo.setUserName(userDTO.getName());
                vo.setUserIcon(userDTO.getIcon());
                }
            }
            //回答者信息分装
            InteractionReply replys = replyMap.get(record.getLatestAnswerId());
            if (ObjectUtil.isNotEmpty(replys)) {
                vo.setLatestReplyContent(replys.getContent());
                UserDTO reply = userInfoMap.get(replys.getUserId());
                if (!replys.getAnonymity()) {
                    if (ObjectUtil.isNotEmpty(reply)) {
                        vo.setLatestReplyUser(reply.getName());
                    }
                }
            }
            voList.add(vo);
        }
        //7.返回pageDTO
        return PageDTO.of(pageQuestion, voList);
    }

    /**
     * 根据id查询问题详情
     *
     * @param id
     * @return
     */
    @Override
    public QuestionVO queryQuestionById(Long id) {
        //1.根据id查询问题详情
        InteractionQuestion question = this.getById(id);
        if (ObjectUtil.isEmpty(question) || question.getHidden()) {
            return null;
        }
        //1.1根据userid查询用户信息
        UserDTO userDTO = null;
        //1.2没有匿名的用户才需要给其赋值昵称和头像
        if (!question.getAnonymity()) {
            userDTO = userClient.queryUserById(question.getUserId());
        }
        //2.将po->vo
        QuestionVO questionVO = BeanUtils.copyBean(question, QuestionVO.class);
        if (ObjectUtil.isNotEmpty(userDTO)) {
            questionVO.setUserName(userDTO.getName());
            questionVO.setUserIcon(userDTO.getIcon());
        }
        return questionVO;
    }

    /**
     * 管理端分页查询
     *
     * @param pageQuery
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> queryQuestionAdmin(QuestionAdminPageQuery pageQuery) {
        //1.根据课程名称查询课程的id集合(模糊查询)
        String courseName = pageQuery.getCourseName();
        List<Long> courseIds = null;
        if (ObjectUtil.isNotEmpty(courseName)) {
            courseIds = searchClient.queryCoursesIdByName(courseName);
        }
        //2.分页查询question表
        //select * from interaction_question where course_id in (1,2,3)
        // and status = 1 and create_time >= '2022-10-27 12:31:44' and  create_time <= '2025-10-27 12:31:44'
        //order by create_time desc limit 0,10;
        LocalDateTime beginTime = pageQuery.getBeginTime();
        LocalDateTime endTime = pageQuery.getEndTime();
        Page<InteractionQuestion> questionPage = this.lambdaQuery()
                .in(ObjectUtil.isNotEmpty(courseIds), InteractionQuestion::getCourseId, courseIds)
                .eq(ObjectUtils.isNotEmpty(pageQuery.getStatus()), InteractionQuestion::getStatus, pageQuery.getStatus())
                .ge(ObjectUtil.isNotEmpty(beginTime), InteractionQuestion::getCreateTime, beginTime)
                .le(ObjectUtil.isNotEmpty(endTime), InteractionQuestion::getUpdateTime, endTime)
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = questionPage.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            //2.1为空返回一个空集合
            PageDTO.empty(0L, 0L);
        }
        //3.获取章，节的名称
        //3.1遍历records获取章 节的ids
        Set<Long> userIds = new HashSet<>(records.size());
        Set<Long> cids = new HashSet<>(records.size());//课程id
        Set<Long> chapterIds = new HashSet<>(records.size());//章节id

        for (InteractionQuestion record : records) {
            cids.add(record.getCourseId());
            //获取章节id
            chapterIds.add(record.getChapterId());
            chapterIds.add(record.getSectionId());

            userIds.add(record.getUserId());
        }
        //3.2根据章，节的ids查询章，节的名称
        List<CataSimpleInfoDTO> cataSectionInfo = catalogueClient.batchQueryCatalogue(chapterIds);
        Map<Long, String> cataSectionInfoMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(cataSectionInfo)) {
            cataSectionInfoMap = cataSectionInfo.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }

        //4.根据courseId查询课程的名称 ， 课程分类名称拼接
        List<CourseSimpleInfoDTO> courseInfos = courseClient.getSimpleInfoList(cids);
        Map<Long, CourseSimpleInfoDTO> courseInfoMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(courseInfos)) {
            //4.1转为map
            courseInfoMap = courseInfos.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, Function.identity()));
        }

        //5.查询提问者昵称
        List<UserDTO> userInfo = userClient.queryUserByIds(userIds);
        Map<Long, String> userInfoMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(userInfo)) {
            //5.1转为map
            userInfoMap = userInfo.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));
        }
        //6.遍历分页结果，组装数据
        //6.1创建一个list集合
        List<QuestionAdminVO> voList = new ArrayList<>();
        //6.2遍历records集合分装数据
        for (InteractionQuestion record : records) {
            //6.3对象拷贝
            QuestionAdminVO vo = BeanUtils.copyBean(record, QuestionAdminVO.class);
            //6.4分装章节的名称
            vo.setChapterName(cataSectionInfoMap.getOrDefault(record.getChapterId(), "0"));
            vo.setSectionName(cataSectionInfoMap.getOrDefault(record.getSectionId(), "0"));
            //6.5封装课程名称和课程分类名称拼接
            CourseSimpleInfoDTO courseInfo = courseInfoMap.get(record.getCourseId());
            vo.setCourseName(courseInfo.getName());
            //6.5.1三级名称分类
            String categoryNames = categoryCache.getCategoryNames(courseInfo.getCategoryIds());
            vo.setCategoryName(categoryNames);
            //6.6封装用户名称
            String userName = userInfoMap.get(record.getUserId());
            if (!BooleanUtils.isTrue(record.getAnonymity())) {
                vo.setUserName(userName);
            }
            //6.7将vo数据添加至voLids
            voList.add(vo);
        }
        //7.组装vo数据并返回
        return PageDTO.of(questionPage, voList);
    }

    /**
     * 删除问题  实战 1
     *
     * @param id
     */
    @Override
    public void deleteQuestion(Long id) {
        this.removeById(id);
    }

    /**
     * 编辑互动问题  实战 2
     *
     * @param questionFormDTO
     */
    @Override
    public void putQuestion(Long id, QuestionFormDTO questionFormDTO) {
        //1.DTO->po
        InteractionQuestion question = BeanUtils.copyBean(questionFormDTO, InteractionQuestion.class);
        question.setId(id);
        //2.修改问题
        boolean isSuccess = this.updateById(question);
        if (!isSuccess) {
            log.error("修改问题失败");
        }
    }

    /**
     * 根据id查询问题详情  实战 5
     *
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO queryQuestionAdminById(Long id) {
        //1.跟据问题id查询问题的详细信息
        InteractionQuestion question = this.lambdaQuery().eq(InteractionQuestion::getId, id).one();
        if (ObjectUtil.isEmpty(question)) {
            return  null;
        }
        //2.根据courseid查询课程名称、课程分类、老师名的ids
        Long courseId = question.getCourseId();
        CourseFullInfoDTO courseFullInfo = courseClient.getCourseInfoById(courseId, false, true);
        log.info("课程的全全部数据为：{}", courseFullInfo);
        //2.1根据老师的ids查询老师的名称、一个课程可以有多个老师
        List<Long> teacherIds = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(courseFullInfo)) {
            teacherIds = courseFullInfo.getTeacherIds();
        }
        //2.2收集章 节 id
        Set<Long> chaps = new HashSet<>();
        chaps.add(question.getChapterId());
        chaps.add(question.getSectionId());
        //2.3调用章节微服务查询章节信息
        List<CataSimpleInfoDTO> cataSectionInfo = catalogueClient.batchQueryCatalogue(chaps);
        //2.3.1转为map
        Map<Long, String> cataSectionInfoMap = new HashMap<>(cataSectionInfo.size());
        if(ObjectUtil.isNotEmpty(cataSectionInfo)){
            cataSectionInfoMap = cataSectionInfo.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));

        }
        //3.根据userId查询用户信息
        Long userId = question.getUserId();
        //5.查询老师的名字
        List<UserDTO> teacherUserDTO = userClient.queryUserByIds(teacherIds);
        //5.1查询用户的信息
        UserDTO userInfo = userClient.queryUserById(userId);
        //5.2.将po->vo
        QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
        //5.3分装课程分类数据
        vo.setCategoryName(categoryCache.getCategoryNames(courseFullInfo.getCategoryIds()));
        //5.4分装课程名称数据
        vo.setCourseName(courseFullInfo.getName());
        //5.5分装所属章节数据
        if(ObjectUtil.isNotEmpty(cataSectionInfoMap)){
            vo.setChapterName(cataSectionInfoMap.getOrDefault(question.getChapterId(),""));
            vo.setSectionName(cataSectionInfoMap.getOrDefault(question.getSectionId(),""));
        }
        //5.6分装老师名称
        String teacherNames = teacherUserDTO.stream().map(UserDTO::getName).collect(Collectors.joining("/"));
        vo.setTeacherName(teacherNames);
        //5.7分装学生数据
        if (!question.getAnonymity()) {
            vo.setUserName(userInfo.getName());
            vo.setUserIcon(userInfo.getIcon());
        }
        //6.返回vo
        return vo;
    }
}
